#include <QDebug>
#include <QFileDialog>
#include "Include/IconProvider.h"
#include "Project.h"
#include "ProjectProperties.h"
#include "Include/IRopeProject.h"
#include "ui_ProjectProperties.h"

ProjectProperties::ProjectProperties(Plugins::Project * prj, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ProjectProperties),
    _project(prj)
{
    ui->setupUi(this);

    ui->pyVersionCmb->addItem("2", 2);
    ui->pyVersionCmb->addItem("3", 3);

    ui->guiVersionCmb->addItem(tr("None"), "");
    ui->guiVersionCmb->addItem(tr("PyQt"), "PyQt");
    ui->guiVersionCmb->addItem(tr("PySide"), "PySide");

    ui->listWidget->item(0)->setData(Qt::UserRole, "props");
    ui->listWidget->item(0)->setIcon(IconProvider::instance()->icon("emblem-system"));

    ui->listWidget->item(1)->setData(Qt::UserRole, "lint");
    ui->listWidget->item(1)->setIcon(IconProvider::instance()->icon("emblem-default"));

    connect(ui->listWidget, SIGNAL(currentRowChanged(int)), SLOT(onMenuChanged(int)));

    ui->nameEdt->setText(_project->name());
    ui->scriptEdt->setText(_project->mainScript());
    ui->pyVersionCmb->setCurrentIndex(ui->pyVersionCmb->findData(_project->pythonVersion()));
    ui->guiVersionCmb->setCurrentIndex(ui->guiVersionCmb->findData(_project->guiVersion()));
    ui->edtShowFiles->setText(_project->showFiles().join(";"));

    setPyLintVars();

    connect(ui->buttonBox, SIGNAL(accepted()), SLOT(onAccept()));
    connect(ui->buttonBox, SIGNAL(rejected()), SLOT(reject()));
    connect(ui->scriptSelectBtn, SIGNAL(clicked()), SLOT(onSelectMainClicked()));

    _style = _project->pylintPreset(0);
    switch(_style){
    case 1: ui->rbCamel->setChecked(true); onCamelToggled(true); break;
    case 2: ui->rbCustom->setChecked(true); onCustomToggled(true); break;
    default: ui->rbUnderscore->setChecked(true); onUnderscoreToggled(true);
    }

    connect(ui->rbCamel, SIGNAL(toggled(bool)), SLOT(onCamelToggled(bool)));
    connect(ui->rbUnderscore, SIGNAL(toggled(bool)), SLOT(onUnderscoreToggled(bool)));
    connect(ui->rbCustom, SIGNAL(toggled(bool)), SLOT(onCustomToggled(bool)));
}

ProjectProperties::~ProjectProperties()
{
    delete ui;
}

void ProjectProperties::onAccept()
{
    _project->setName(ui->nameEdt->text());
    _project->setMainScript(ui->scriptEdt->text());
    _project->setPythonVersion(ui->pyVersionCmb->itemData(ui->pyVersionCmb->currentIndex()).toInt());
    _project->setShowFiles(ui->edtShowFiles->text().split(";"));
    _project->setGuiVersion(ui->guiVersionCmb->itemData(ui->guiVersionCmb->currentIndex()).toString());

    savePyLintVars();
    accept();
}

void ProjectProperties::setPyLintVars()
{
    ui->edtDummyVar->setText(_project->lintConfig("dummyVar", "_|dummy").toString());
    ui->edtBadFunc->setText(_project->lintConfig("badFunc", "map, filter, apply, input").toString());
    ui->edtGoodNames->setText(_project->lintConfig("goodNames", "i, j, k, ex, Run, _").toString());
    ui->edtBadNames->setText(_project->lintConfig("badNames", "foo, bar, baz").toString());
    ui->edtMaxLineLength->setValue(_project->lintConfig("maxLineLength", 80).toInt());
    ui->edtMaxModLines->setValue(_project->lintConfig("maxModLines", 1000).toInt());


    ui->edtModule->setText(_project->lintConfig("checkModule", "(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$").toString());
    ui->edtConst->setText(_project->lintConfig("checkConst", "(([A-Z_][A-Z0-9_]*)|(__.*__))$").toString());
    ui->edtClass->setText(_project->lintConfig("checkClass", "[A-Z_][a-zA-Z0-9]+$").toString());
    ui->edtFunc->setText(_project->lintConfig("checkFunc", "[a-z_][a-z0-9_]{2,30}$").toString());
    ui->edtMethod->setText(_project->lintConfig("checkMethod", "[a-z_][a-z0-9_]{2,30}$").toString());
    ui->edtAttr->setText(_project->lintConfig("checkAttr", "[a-z_][a-z0-9_]{2,30}$").toString());
    ui->edtArg->setText(_project->lintConfig("checkArg", "[a-z_][a-z0-9_]{2,30}$").toString());
    ui->edtVar->setText(_project->lintConfig("checkVar", "[a-z_][a-z0-9_]{2,30}$").toString());
    ui->edtInlineVar->setText(_project->lintConfig("checkInlineVar", "[A-Za-z_][A-Za-z0-9_]*$").toString());

    ui->edtIgnArgNames->setText(_project->lintConfig("ignArgNames", "_.*").toString());
    ui->edtMaxArgs->setValue(_project->lintConfig("maxArgs", 5).toInt());
    ui->edtMaxLocals->setValue(_project->lintConfig("maxLocals", 15).toInt());
    ui->edtMaxReturns->setValue(_project->lintConfig("maxReturns", 6).toInt());
    ui->edtMaxBranchs->setValue(_project->lintConfig("maxBranchs", 12).toInt());
    ui->edtMaxStats->setValue(_project->lintConfig("maxStats", 50).toInt());
    ui->edtMaxParents->setValue(_project->lintConfig("maxParents", 7).toInt());
    ui->edtMaxAttrs->setValue(_project->lintConfig("maxAttrs", 7).toInt());
    ui->edtMinPublic->setValue(_project->lintConfig("minPublic", 2).toInt());
    ui->edtMaxPublic->setValue(_project->lintConfig("maxPublic", 20).toInt());
}

void ProjectProperties::savePyLintVars()
{
    if (
        _project->setLintConfig("dummyVar", ui->edtDummyVar->text()) ||
        _project->setLintConfig("goodNames", ui->edtGoodNames->text())  ||
        _project->setLintConfig("badNames", ui->edtBadNames->text()) ||
        _project->setLintConfig("badFunc", ui->edtBadFunc->text()) ||
        _project->setLintConfig("maxLineLength", ui->edtMaxLineLength->value()) ||
        _project->setLintConfig("maxModLines", ui->edtMaxModLines->value()) ||

        _project->setLintConfig("checkModule", ui->edtModule->text()) ||
        _project->setLintConfig("checkConst", ui->edtConst->text()) ||
        _project->setLintConfig("checkClass", ui->edtClass->text()) ||
        _project->setLintConfig("checkFunc", ui->edtFunc->text()) ||
        _project->setLintConfig("checkMethod", ui->edtMethod->text()) ||
        _project->setLintConfig("checkAttr", ui->edtAttr->text()) ||
        _project->setLintConfig("checkArg", ui->edtArg->text()) ||
        _project->setLintConfig("checkVar", ui->edtVar->text()) ||
        _project->setLintConfig("checkInlineVar", ui->edtInlineVar->text()) ||

        _project->setLintConfig("ignArgNames", ui->edtIgnArgNames->text()) ||
        _project->setLintConfig("maxArgs", ui->edtMaxArgs->value()) ||
        _project->setLintConfig("maxLocals", ui->edtMaxLocals->value()) ||
        _project->setLintConfig("maxReturns", ui->edtMaxReturns->value()) ||
        _project->setLintConfig("maxBranchs", ui->edtMaxBranchs->value()) ||
        _project->setLintConfig("maxStats", ui->edtMaxStats->value()) ||
        _project->setLintConfig("maxParents", ui->edtMaxParents->value()) ||
        _project->setLintConfig("maxAttrs", ui->edtMaxAttrs->value()) ||
        _project->setLintConfig("minPublic", ui->edtMinPublic->value()) ||
        _project->setLintConfig("maxPublic", ui->edtMaxPublic->value())
    ) {
        _project->rope()->revalidate(_project->path(), _project->mainScript(), _project->filename());
    }
    _project->setPylintPreset(_style);
}

void ProjectProperties::onSelectMainClicked()
{
    QString mainScriptFile = QFileDialog::getOpenFileName(this, trUtf8("Select Main Script"), _project->path());
    if (!mainScriptFile.isEmpty()){
        QDir dir(_project->path());
        ui->scriptEdt->setText(dir.relativeFilePath(mainScriptFile));
    }
}

void ProjectProperties::onMenuChanged(int row)
{
    ui->stackedWidget->setCurrentIndex(row);
}

void ProjectProperties::onCamelToggled(bool toggle)
{
    if (!toggle)
        return

    ui->edtModule->setText("(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$");
    ui->edtModule->setEnabled(false);
    ui->edtConst->setText("(([A-Z_][A-Z0-9_]*)|(__.*__))$");
    ui->edtConst->setEnabled(false);
    ui->edtClass->setText("[A-Z_][a-zA-Z0-9]+$");
    ui->edtClass->setEnabled(false);
    ui->edtFunc->setText("[a-z_][a-zA-Z0-9_]{2,30}$");
    ui->edtFunc->setEnabled(false);
    ui->edtMethod->setText("[a-z_][a-zA-Z0-9_]{2,30}$");
    ui->edtMethod->setEnabled(false);
    ui->edtAttr->setText("[a-z_][a-zA-Z0-9_]{2,30}$");
    ui->edtAttr->setEnabled(false);
    ui->edtArg->setText("[a-z_][a-zA-Z0-9_]{2,30}$");
    ui->edtArg->setEnabled(false);
    ui->edtVar->setText("[a-z_][a-zA-Z0-9_]{2,30}$");
    ui->edtVar->setEnabled(false);
    ui->edtInlineVar->setText("[A-Za-z_][A-Za-z0-9_]*$");
    ui->edtInlineVar->setEnabled(false);
    _style = 1;
}

void ProjectProperties::onUnderscoreToggled(bool toggle)
{
    if (!toggle)
        return;

    ui->edtModule->setText("(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$");
    ui->edtModule->setEnabled(false);
    ui->edtConst->setText("(([A-Z_][A-Z0-9_]*)|(__.*__))$");
    ui->edtConst->setEnabled(false);
    ui->edtClass->setText("[A-Z_][a-zA-Z0-9]+$");
    ui->edtClass->setEnabled(false);
    ui->edtFunc->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtFunc->setEnabled(false);
    ui->edtMethod->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtMethod->setEnabled(false);
    ui->edtAttr->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtAttr->setEnabled(false);
    ui->edtArg->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtArg->setEnabled(false);
    ui->edtVar->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtVar->setEnabled(false);
    ui->edtInlineVar->setText("[A-Za-z_][A-Za-z0-9_]*$");
    ui->edtInlineVar->setEnabled(false);
    _style = 0;
}

void ProjectProperties::onCustomToggled(bool toggle)
{
    if (!toggle)
        return;

    ui->edtModule->setText("(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$");
    ui->edtModule->setEnabled(true);
    ui->edtConst->setText("(([A-Z_][A-Z0-9_]*)|(__.*__))$");
    ui->edtConst->setEnabled(true);
    ui->edtClass->setText("[A-Z_][a-zA-Z0-9]+$");
    ui->edtClass->setEnabled(true);
    ui->edtFunc->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtFunc->setEnabled(true);
    ui->edtMethod->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtMethod->setEnabled(true);
    ui->edtAttr->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtAttr->setEnabled(true);
    ui->edtArg->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtArg->setEnabled(true);
    ui->edtVar->setText("[a-z_][a-z0-9_]{2,30}$");
    ui->edtVar->setEnabled(true);
    ui->edtInlineVar->setText("[A-Za-z_][A-Za-z0-9_]*$");
    ui->edtInlineVar->setEnabled(true);
    _style = 2;
}
